package com.atguigu.gmall.payment.controller;

import com.alipay.api.AlipayApiException;
import com.alipay.api.internal.util.AlipaySignature;
import com.atguigu.gmall.common.result.Result;
import com.atguigu.gmall.model.enums.PaymentStatus;
import com.atguigu.gmall.model.enums.PaymentType;
import com.atguigu.gmall.model.payment.PaymentInfo;
import com.atguigu.gmall.payment.config.AlipayConfig;
import com.atguigu.gmall.payment.service.AlipayService;
import com.atguigu.gmall.payment.service.PaymentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.annotation.PostConstruct;
import java.math.BigDecimal;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Controller
@RequestMapping("/api/payment/alipay")
public class AlipayController {

    @Autowired
    private AlipayService alipayService;

    @Autowired
    private PaymentService paymentService;

    @Autowired
    private RedisTemplate redisTemplate;

    @Value("${app_id}")
    private String app_id;


    @RequestMapping("submit/{orderId}")
     @ResponseBody
    public String submitOrder(@PathVariable Long orderId){
        String from = alipayService.createaliPay(orderId);
        return from;
    }

    /**
     * 支付成功以后同步回调页面显示支付成功
     */
    @GetMapping("callback/return")
    public String callBack(){
        System.out.println(AlipayConfig.notify_payment_url);
        // 重定向到weball得controller中渲染页面
        return "redirect:"+ AlipayConfig.return_order_url;
    }


    /**
     * 异步回调地址，
     * 因为我们得项目在本地，支付宝接口在公网上，所以支付宝
     * 访问我们得内网是访问不到得，这里配置了内网穿透，使用内网穿透生成域名
     * @param paramsMap 支付宝接口给我们返回得数据
     * @return
     */
    @PostMapping("/callback/notify")
    @ResponseBody
    public String callbackNotify(@RequestParam Map<String,String> paramsMap){
        System.out.println("1111------------------");
        try {
            // 验证前四步：
            // 1.验证参数
            // 2. 验证公钥
            // 3. 验证字符集
            // 4. 验证算法 这里使用得是SRA2
            // 这四个只要有一个验证不通过都会返回false
            boolean signVerified = AlipaySignature.rsaCheckV1(paramsMap, AlipayConfig.alipay_public_key, AlipayConfig.charset, AlipayConfig.sign_type); //调用SDK验证签名

            // 获取out_trade_no
            String out_trade_no = paramsMap.get("out_trade_no");
            // 获取total_amount
            String total_amount = paramsMap.get("total_amount");
            // 获取app_id
            String appId = paramsMap.get("app_id");
            //  保证异步通知的幂等性！notify_id
            String notifyId = paramsMap.get("notify_id");
            //  获取异步通知的参数中的交易状态！
            String tradeStatus = paramsMap.get("trade_status");

            // 获取mysql交易记录
            PaymentInfo paymentInfo = this.paymentService.getPaymentInfo(out_trade_no, PaymentType.ALIPAY.name());
            // 如果返回得是true，则表示验证通过，
            if(paymentInfo == null || !signVerified || !out_trade_no.equals(paymentInfo.getOutTradeNo())
            || new BigDecimal("0.01").compareTo(new BigDecimal(total_amount)) != 0 || !appId.equals(app_id)){
                // TODO 验签失败则记录异常日志，并在response中返回failure.
                return "failure";
            }
            // 使用redis 将notifyId 使用setnx存储到redis 保证订单得幂等性
            Boolean aBoolean = this.redisTemplate.opsForValue().setIfAbsent(notifyId, notifyId, 1462 * 60, TimeUnit.SECONDS);
            if (!aBoolean) return "failure";

            // 判断支付宝传回来得订单状态，只有这两种才会调用异步回调，继续执行下面得代码
            if ("TRADE_SUCCESS".equals(tradeStatus) || "TRADE_FINISHED".equals(tradeStatus)){
                // 修改订单状态
                this.paymentService.updatePayMentInfo(out_trade_no,PaymentType.ALIPAY.name(),paramsMap);

                // 返回success
                return "success";

            }else{
                return "failure";
            }



        } catch (AlipayApiException e) {
            e.printStackTrace();
        }

        return "failure";
    }

    // 发起退款！http://localhost:8205/api/payment/alipay/refund/20
    @RequestMapping("refund/{orderId}")
    @ResponseBody
    public Result refund(@PathVariable(value = "orderId")Long orderId) {
        // 调用退款接口
        boolean flag = paymentService.refund(orderId);

        return Result.ok(flag);
    }

}
